package com.client.job.runLogs;

import com.alibaba.fastjson.JSON;
import com.client.job.core.config.TaskRegisterCompent;
import com.client.job.core.model.MJob;
import com.client.job.core.model.MJobRunLog;
import com.client.job.core.model.MJobRunLogsVo;
import com.client.job.socket.ClientByNettyClient;
import com.client.job.utils.DataResult;
import com.client.job.utils.DateUtil;
import com.client.job.utils.SpringUtil;

import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Timer;
import java.util.TimerTask;


/**
 * 日志工厂
 *
 * @author mnengxiangzhong
 * @version 1.0
 * @date 2021/9/22/022
 */
@Slf4j
public class RunLogsFactory {

    /**
     * 本地线程
     */
    public static ThreadLocal<MJobRunLogsVo> voThreadLocal = new ThreadLocal<>();

    /**
     * 本地日志存储容器
     */
    private static Map<MJobRunLogsVo, List<MJobRunLog>> logMap = new HashMap<>();

    /**
     * 定时任务执行器
     */
    private static Timer timer = new Timer();
    
    /**
     * 最大存储日志数量（推送临界值）
     */
    private static Integer maxLogsCounts = 20;

    /**
     * 单个Job日志长度不超过100条
     */
    private static Integer oneLogLimitCounts = 100 ;

    /**
     * 执行线程池
     */
    private static LogsThreadPoolProxy<?>  proxy ;
    




    static {
        if(proxy == null){
            proxy = new LogsThreadPoolProxy<>();
        }
        timer.schedule(new TimerTask() {

            @Override
            public void run() {
                if (logMap.isEmpty()) {
                    return;
                }
                for (Entry<MJobRunLogsVo, List<MJobRunLog>> e : logMap.entrySet()) {
                    e.getKey().getLogList().addAll(e.getValue());
                    pushLogs(e.getKey());
                }
                logMap.clear();
            }
        }, 1000 * 60L, 1000 * 60L);
    }

    /**
     * 初始化工厂
     *
     * @return
     */
    public static RunLogsFactory buildFactory() {
        return new RunLogsFactory();
    }

    /**
     * 构建Job
     *
     * @return
     */
    public RunLogsFactory job(MJob mjob) {
        MJobRunLogsVo vo = new MJobRunLogsVo();
        vo.setJobId(mjob.getJobId());
        vo.setJobName(mjob.getJobName());
        if (vo.getLogList() == null) {
            vo.setLogList(new ArrayList<>());
        }
        voThreadLocal.set(vo);
        return new RunLogsFactory();
    }

    /**
     * 构建日志
     *
     * @param runLog
     * @return
     */
    public RunLogsFactory logs(String runLog) {
        Date currentDate = new Date();
        log.info(DateUtil.parseDateToStr(DateUtil.YYYY_MM_DD_HH_MM_SS, currentDate) + ":{}", runLog);
        MJobRunLogsVo vo = voThreadLocal.get();
        if (vo == null) {
            //未构建Mjob对象，仅打印日志即可
            voThreadLocal.remove();
            return this;
        }
        //加入容器中队列中
        List<MJobRunLog> logList = logMap.get(vo);
        if (logList == null) {
            logMap.put(vo, new ArrayList<>());
        }

        if(logList.size() > oneLogLimitCounts){
            voThreadLocal.remove();
            logMap.remove(vo);
            return  this;
        }
        logList.add(MJobRunLog.builder().dealTime(currentDate).log(runLog).build());
        logMap.put(vo, logList);
        return this;
    }

    /**
     * 推送日志
     */
    public void send() {
        MJobRunLogsVo vo = voThreadLocal.get();
        if (vo == null) {
            //未构建Mjob对象
            voThreadLocal.remove();
            return;
        }
        //日志推送
        List<MJobRunLog> logList = logMap.get(vo);
        if (logList.size() > maxLogsCounts) {
            vo.setLogList(logList);
        	pushLogs(vo);
            logMap.remove(vo);
        }
        voThreadLocal.remove();
    }


    /**
     * 日志推送
     * @param logsVo
     */
    private static void pushLogs(MJobRunLogsVo  logsVo){
        proxy.commitTask(new Runnable() {
            @Override
            public void run() {
            	  TaskRegisterCompent cm = SpringUtil.getBean(TaskRegisterCompent.class);
            	  logsVo.setAppName(cm.getServerInfo().get(0));
            	  logsVo.setPort(cm.getServerInfo().get(1));
            	  DataResult result = DataResult.buildSuccess(logsVo).buildRequestType(1);
                  ClientByNettyClient.sengMessage(JSON.toJSONString(result));
            }
        });
    }

}
